/*
 * Copyright (c) 2024 Huawei Device Co., Ltd.
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include "napi/PagCompositionProxy.h"
#include <bits/alltypes.h>
#include "napi/pag_napi_pagFile.h"

namespace NativeXComponentSample {

const int32_t STR_DEFAULT_SIZE = 2048;
const int32_t INDEX_0 = 0;
const int32_t INDEX_1 = 1;
const int32_t INDEX_2 = 2;
const int32_t INDEX_3 = 3;
const int32_t PARAM_COUNT_1 = 1;
const int32_t PARAM_COUNT_2 = 2;
const int32_t PARAM_COUNT_3 = 3;
const int32_t PARAM_COUNT_4 = 4;

const unsigned int LOG_PRINT_DOMAIN = 0XFF00;

std::unordered_map<std::string, std::shared_ptr<pag::PAGComposition>> g_pagCompositionMap_ = {};

std::unordered_map<std::string, PagCompositionProxy *> PagCompositionProxy::PagCompositionProxyMap_ = {};

PagCompositionProxy::PagCompositionProxy(std::string &id) : id_(id)
{
    if (id != "") {
        PagCompositionProxy::PagCompositionProxyMap_[id] = this;
    }
}

PagCompositionProxy::~PagCompositionProxy()
{
    if (mRef != nullptr) {
        napi_delete_reference(mEnv, mRef);
    }
}

napi_value PagCompositionProxy::PAGCompositionInit(napi_env env, napi_callback_info info)
{
    size_t argc = PARAM_COUNT_2;
    napi_value args[INDEX_2] = { nullptr };
    napi_get_cb_info(env, info, &argc, args, nullptr, nullptr);
    
    OH_LOG_Print(LOG_APP, LOG_INFO, LOG_PRINT_DOMAIN, "PagCompositionProxy",
                 "YY -- PAGCompositionInit %{public}s", id_.c_str());
    int32_t width = 0;
    napi_get_value_int32(env, args[0], &width);
    
    int32_t height = 0;
    napi_get_value_int32(env, args[1], &height);
    m_pagComposition = pag::PAGComposition::Make(width, height);
    g_pagCompositionMap_[id_] = m_pagComposition;
    return nullptr;
}

napi_value PagCompositionProxy::AddLayer(napi_env env, napi_callback_info info)
{
    if (g_pagCompositionMap_[id_] != nullptr) {
        std::shared_ptr<pag::PAGFile> obj(g_pagFile);
        g_pagCompositionMap_[id_]->addLayer(obj);
        OH_LOG_Print(LOG_APP, LOG_INFO, LOG_PRINT_DOMAIN, "PagCompositionProxy",
                     "AddLayer::g_pagComposition %{public}p", obj.get());
        return nullptr;
    }
    OH_LOG_Print(LOG_APP, LOG_INFO, LOG_PRINT_DOMAIN, "PagCompositionProxy",
        "YY -- AddLayer g_pagCompositionMap_[xComponentId] is nullptr");
    return nullptr;
}

napi_value PagCompositionProxy::GetLayerAt(napi_env env, napi_callback_info info)
{
    size_t argc = PARAM_COUNT_1;
    napi_value args[INDEX_1] = { nullptr };
    napi_get_cb_info(env, info, &argc, args, nullptr, nullptr);

    int32_t index = 0;
    napi_get_value_int32(env, args[0], &index);
    OH_LOG_Print(LOG_APP, LOG_INFO, LOG_PRINT_DOMAIN, "PagCompositionProxy", "YY -- GetLayerAt index = %{public}d",
        index);

    if (g_pagCompositionMap_[id_] != nullptr) {
        std::shared_ptr<pag::PAGLayer> pagLayer = g_pagCompositionMap_[id_]->getLayerAt(index);
        g_pagFile = std::static_pointer_cast<pag::PAGFile>(pagLayer);
        return nullptr;
    }
    OH_LOG_Print(LOG_APP, LOG_INFO, LOG_PRINT_DOMAIN, "PagCompositionProxy",
                 "YY -- AddLayer g_pagCompositionMap_[xComponentId] is nullptr");
    return nullptr;
}

napi_value PagCompositionProxy::RemoveLayer(napi_env env, napi_callback_info info)
{
    if (g_pagCompositionMap_[id_] != nullptr) {
        g_pagCompositionMap_[id_]->removeLayer(g_pagFile);
        return nullptr;
    }
    OH_LOG_Print(LOG_APP, LOG_INFO, LOG_PRINT_DOMAIN, "PagCompositionProxy",
                 "YY -- RemoveLayer g_pagCompositionMap_[xComponentId] is nullptr");
    return nullptr;
}

napi_value PagCompositionProxy::RemoveAllLayers(napi_env env, napi_callback_info info)
{
    if (g_pagCompositionMap_[id_] != nullptr) {
        g_pagCompositionMap_[id_]->removeAllLayers();
        return nullptr;
    }
    OH_LOG_Print(LOG_APP, LOG_INFO, LOG_PRINT_DOMAIN, "PagCompositionProxy",
                 "YY -- RemoveAllLayers g_pagCompositionMap_[xComponentId] is nullptr");
    return nullptr;
}

napi_value PagCompositionProxy::NumChildren(napi_env env, napi_callback_info info)
{
    napi_value result;
    if (g_pagCompositionMap_[id_] != nullptr) {
        napi_status status = napi_create_int64(env, g_pagCompositionMap_[id_]->numChildren(), &result);
        OH_LOG_Print(LOG_APP, LOG_INFO, LOG_PRINT_DOMAIN, "PagCompositionProxy", "YY -- numChildren %{public}ld",
                     m_pagComposition->numChildren());
        return result;
    }
    OH_LOG_Print(LOG_APP, LOG_INFO, LOG_PRINT_DOMAIN, "PagCompositionProxy",
                 "YY -- numChildren g_pagCompositionMap_[xComponentId] is nullptr");
    return nullptr;
}

napi_value PagCompositionProxy::AddLayerAt(napi_env env, napi_callback_info info)
{
    size_t argc = PARAM_COUNT_1;
    napi_value args[INDEX_1] = {nullptr};
    napi_get_cb_info(env, info, &argc, args, nullptr, nullptr);

    int32_t index = 0;
    napi_get_value_int32(env, args[0], &index);

    OH_LOG_Print(LOG_APP, LOG_INFO, LOG_PRINT_DOMAIN, "PagCompositionProxy", "AddLayerAt index = %{public}d",
        index);
    if (g_pagCompositionMap_[id_] != nullptr) {
        std::shared_ptr<pag::PAGFile> obj(g_pagFile);
        g_pagCompositionMap_[id_]->addLayerAt(obj, index);
        OH_LOG_Print(LOG_APP, LOG_INFO, LOG_PRINT_DOMAIN, "PagCompositionProxy",
            "AddLayerAt g_pagComposition%{public}p", m_pagComposition.get());
        return nullptr;
    }
    OH_LOG_Print(LOG_APP, LOG_INFO, LOG_PRINT_DOMAIN, "PagCompositionProxy",
                 "YY -- AddLayerAt g_pagCompositionMap_[xComponentId] is nullptr");
    return nullptr;
}

napi_value PagCompositionProxy::RemoveLayerAt(napi_env env, napi_callback_info info)
{
    size_t argc = PARAM_COUNT_1;
    napi_value args[INDEX_1] = {nullptr};
    napi_get_cb_info(env, info, &argc, args, nullptr, nullptr);

    int32_t index = 0;
    napi_get_value_int32(env, args[0], &index);
    OH_LOG_Print(LOG_APP, LOG_INFO, LOG_PRINT_DOMAIN, "PagCompositionProxy", "RemoveLayerAt index = %{public}d",
                 index);

    if (g_pagCompositionMap_[id_] != nullptr) {
        g_pagCompositionMap_[id_]->removeLayerAt(index);
        OH_LOG_Print(LOG_APP, LOG_INFO, LOG_PRINT_DOMAIN, "PagCompositionProxy",
            "RemoveLayerAt g_pagComposition%{public}p", m_pagComposition.get());
        return nullptr;
    }
    return nullptr;
}
}